/**********************************************************************
 * @file keyboard.c
 **********************************************************************/
#include "./include/keyboard.h"
#include "./include/2440addr.h"
#include "./include/interrupt.h"
#include "./include/led.h"
#include "./include/uart.h"

// typedef struct KeyIOBit{
// 	UINT32 conAddr;
// 	UINT32 dataAddr;
// 	UINT32 conBitShift;
// 	UINT32 contbitWidth;
// 	UINT32 dataBit;
// }KeyIOBit;

// // TODO: 1. 检测多个按键按下的情况
// // TODO: 2. 检测按键的状态，按下/保持/抬起

// // 矩阵键盘扫描
// // Key0-->EINT1-->GPF1
// // Key1-->EINT3-->GPF3
// // Key2-->EINT7-->GPF7
// // Key3-->EINT11-->GPG3
// // Key4-->EINT17-->GPG9
// // Key5-->SPIMISO-->GPE11
// // Key6-->GPE15
// // Key7-->GPB1

// #define KEY_MATRIC_ROW 4
// #define KEY_MATRIC_COL 4

// KeyIOBit g_KeyIOBit_Col[KEY_MATRIC_COL]={
// 	{ 0x56000050, 0x56000054, 2,  2, 1,},//key0,
// 	{ 0x56000050, 0x56000054, 6,  2, 3,},//key1
// 	{ 0x56000060, 0x56000064, 0,  2, 0,},//key2
// 	{ 0x56000060, 0x56000064, 10, 2, 5,},//key3
// };

// KeyIOBit g_KeyIOBit_Row[KEY_MATRIC_ROW]={
// 	{ 0x56000060, 0x56000064, 18, 2, 9, },//key4
// 	{ 0x56000040, 0x56000044, 22, 2, 11,},//key5
// 	{ 0x56000040, 0x56000044, 30, 2, 15,},//key7
// 	{ 0x56000010, 0x56000014, 2,  2, 1, },//key6
// };

// void SetKeyAttr(KeyIOBit *BitPort,int attr){
// 	int conMask=(1<<BitPort->contbitWidth)-1;
// 	*((volatile unsigned *)BitPort->conAddr) &=~
// (conMask<<BitPort->conBitShift); 	if(attr){
// 		*((volatile unsigned *)BitPort->conAddr) |=
// (0x1<<BitPort->conBitShift);//输出
// 		*((volatile unsigned *)BitPort->dataAddr) &=
// ~(0x1<<BitPort->dataBit);//低电平
// 	}
// 	else
// 		*((volatile unsigned *)BitPort->conAddr) |=
// (0x0<<BitPort->conBitShift);//输入
// }
// //
// UINT32 IsKeyPressed(KeyIOBit *bitPort,int num){
// 	//配置为输入端口
// 	UINT32 value;
// 	for(int i=0;i<num;i++){
// 		value=*((volatile unsigned *)bitPort[i].dataAddr);
// 		if(!(value & (1<<bitPort[i].dataBit)))
// 			return (i+1);
// 	}
// 	return 0;
// }

// void delayMs(int ms)
// {
// 	int num1,num2;
// 	num1=400;
// 	num2=1000;
// 	while(ms-->0){
// 		while(num1-->0){
// 			while(num2-->0);
// 		}
// 	}
// }

// int scanKeyboard(void){
// 	static int lastPressKey=0;
// 	int pressedKey;
// 	int i;
// 	int pressedRowNo,pressedColNo;
// 	if(1){
// 		//设置行信号为输出方式
// 		for(i=0;i<sizeof(g_KeyIOBit_Row)/sizeof(KeyIOBit);i++){
// 			SetKeyAttr(&g_KeyIOBit_Row[i],1);
// 		}
// 		//设置为输入模式
// 		for(i=0;i<sizeof(g_KeyIOBit_Col)/sizeof(KeyIOBit);i++){
// 			SetKeyAttr(&g_KeyIOBit_Col[i],0);
// 		}
// 	}
// 	pressedColNo=IsKeyPressed(g_KeyIOBit_Col,sizeof(g_KeyIOBit_Col)/sizeof(KeyIOBit));
// 	if(!pressedColNo){
// 		lastPressKey=0;
// 		return 0;
// 	}
// 	//延时20ms;
// 	//delayMs(20);
// 	for(i=0;i<sizeof(g_KeyIOBit_Col)/sizeof(KeyIOBit);i++){
// 		SetKeyAttr(&g_KeyIOBit_Col[i],1);
// 	}
// 	//设置为输入模式
// 	for(i=0;i<sizeof(g_KeyIOBit_Row)/sizeof(KeyIOBit);i++){
// 		SetKeyAttr(&g_KeyIOBit_Row[i],0);
// 	}
// 	pressedRowNo=IsKeyPressed(g_KeyIOBit_Row,sizeof(g_KeyIOBit_Row)/sizeof(KeyIOBit));
// 	if(!pressedRowNo){
// 		lastPressKey=0;
// 		return 0;
// 	}
// 	pressedKey=(pressedRowNo-1)*KEY_MATRIC_COL+pressedColNo;
// 	if(pressedKey==lastPressKey)
// 		return 0;
// 	lastPressKey=pressedKey;
// 	return pressedKey;
// }

#define GPF0_KEY_IN ~(3 << 0)
#define GPF2_KEY_IN ~(3 << 4)
#define GPG3_KEY_IN ~(3 << 6)
#define GPG11_KEY_IN ~(3 << 22)

//删去__irq后中断可以正常执行
//对比加__irq和无__irq的反汇编程序
// 加__irq的反汇编最后一行为 subs pc,lr,#4,
// 无__irq的反汇编的最后一行为 bx lr
// 这里key_isr是由

void key_isr(void) {

  UINT32 oft = rINTPND;
  UINT32 val;

  switch (oft) {
  case BIT_EINT0:
    dbg_printf("eint 0\n");
    break;
  case BIT_EINT2:
    dbg_printf("eint 2\n");
    break;
  case BIT_EINT8_23:
    val = rEINTPEND;
    if (val & (1 << 11)) {
      rEINTPEND |= 1 << 11;
      dbg_printf("eint 11\n");
    } else if (val & (1 << 19)) {
      rEINTPEND |= 1 << 19;
      dbg_printf("eint 19\n");
    }
    break;
  default:
    break;
  }

  ClearPending(BIT_EINT0 | BIT_EINT2 | BIT_EINT8_23);
}

void key_init(void) {
  rGPFCON &= (~1);
  rGPFCON |= 1 << 1;
  rGPFCON &= (~(1 << 4));
  rGPFCON |= 1 << 5;

  rGPGCON &= ~(1 << 6);
  rGPGCON |= 1 << 7;
  rGPGCON &= (~(1 << 22));
  rGPGCON |= 1 << 23;

  rEXTINT0 &= ~(1 << 2);
  rEXTINT0 |= (1 << 1);

  rEXTINT0 &= ~(1 << 10);
  rEXTINT0 |= (1 << 9);

  rEXTINT1 &= ~(1 << 14);
  rEXTINT1 |= ((1 << 13) | (1 << 15));

  rEXTINT2 &= ~(1 << 14);
  rEXTINT2 |= ((1 << 13) | (1 << 15));

  rEINTMASK &= (~(1 << 11)) & (~(1 << 19));

  rPRIORITY = 0;
  rINTMSK &= (~(1 << 0) & (~(1 << 2)) & (~(1 << 5)));

  interrupt_regIRQIsr(INT_EINT0, (UINT32)key_isr);
  interrupt_regIRQIsr(INT_EINT2, (UINT32)key_isr);
  interrupt_regIRQIsr(INT_EINT8_23, (UINT32)key_isr);

  ClearPending(BIT_EINT0 | BIT_EINT2 | BIT_EINT8_23);
  EnableIrq(BIT_EINT0 | BIT_EINT2 | BIT_EINT8_23);
}